<template>
	<!-- 二次封装上传 -->
	<el-upload
		class="uploadRef"
		ref="uploadRef"
		:action="realAction"
		:headers="realHeaders"
		:data="data"
		:multiple="multiple"
		:show-file-list="false"
		:drag="drag"
		:limit="limit"
		:disabled="disabled"
		:accept="accept"
		:file-list="modelValue"
		:before-upload="beforeUpload"
		:on-exceed="handleExceed"
		:on-success="handleSuccess"
		:on-error="handleError"
		:on-remove="handleRemove"
		v-bind="$attrs"
	>
		<!-- 默认插槽：点击上传 -->
		<slot>
			<div v-if="autoSlot">
				<slot></slot>
			</div>
			<div
				v-else
				class="imgWrap"
				:style="{
					width,
					height,
				}"
			>
				<img v-if="imgModel" :src="imgModel" class="avatar" />
				<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
			</div>
		</slot>

		<!-- tip 插槽：提示文字 -->
		<template #tip>
			<slot name="tip">
				<div v-if="tip" class="el-upload__tip">
					<p>
						{{ tip }}
					</p>
					<!-- <div>更新LOGO</div> -->
				</div>
			</slot>
		</template>

		<!-- 拖拽插槽（透传） -->
		<template v-if="drag" #default>
			<slot name="drag">
				<div class="el-upload__text">
					<el-icon><upload-filled /></el-icon>
					<div>将文件拖到此处，或<em>点击上传</em></div>
				</div>
			</slot>
		</template>
	</el-upload>
</template>

<script setup lang="ts">
import type { UploadProps, UploadRawFile, UploadFile } from 'element-plus'
import { ElMessage } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
import { tokenStorage } from '@/utils/storage'
// import { useGlobalStore } from '@/stores/global' // 全局 store，用来拿 token
import { genFileId } from 'element-plus'
interface Props {
	modelValue: UploadFile[]
	action?: string
	headers?: Record<string, string>
	data?: Record<string, any>
	accept?: string
	multiple?: boolean
	drag?: boolean
	limit?: number
	disabled?: boolean
	maxSize?: number // 单位 MB
	tip?: string
	imgModel?: string
	width?: string | number
	height?: string | number
	single?: boolean //只上传一个文件，前一个文件替代后一文件
	autoSlot?: boolean
}

const props = withDefaults(defineProps<Props>(), {
	action: '/api/foundation/client/upload/image', // 默认上传地址
	multiple: false,
	drag: false,
	limit: 1,
	disabled: false,
	maxSize: 10,
	width: '308px',
	height: '181px',
	autoSlot: false,
})

const emit = defineEmits<{
	'update:modelValue': [files: UploadFile[]]
	'update:imgModel': [val: string]
	success: [response: any, file: UploadFile, fileList: UploadFile[]]
	error: [err: any, file: UploadFile, fileList: UploadFile[]]
	exceed: [files: File[], fileList: UploadFile[]]
}>()

// const globalStore = useGlobalStore()
const uploadRef = ref()

// 自动注入 token
const realHeaders = computed(() => ({
	Authorization: `Bearer ${tokenStorage.get() || ''}`,
	...props.headers,
}))

// 为了支持自定义 action
const realAction = computed(() => props.action)

// 上传前校验
const beforeUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => {
	const { maxSize, accept } = props

	// 1. 文件类型
	if (
		accept &&
		!accept.split(',').some((type) => rawFile.type.includes(type))
	) {
		ElMessage.error(`文件格式不正确，支持 ${accept}`)
		return false
	}

	// 2. 文件大小
	if (rawFile.size / 1024 / 1024 > maxSize) {
		ElMessage.error(`文件大小不能超过 ${maxSize}MB`)
		return false
	}

	return true
}

// 超出限制
const handleExceed: UploadProps['onExceed'] = (files, fileList) => {
	uploadRef.value!.clearFiles()
	const file = files[0] as UploadRawFile
	file.uid = genFileId()
	uploadRef.value!.handleStart(file)
}
// 上传成功
const handleSuccess: UploadProps['onSuccess'] = (response, file, fileList) => {
	console.log(response, file, fileList)
	if (response?.code === 200) {
		response.data && emit('update:imgModel', response.data.imageUrl)
	}
	emit('update:modelValue', fileList)
	emit('success', response, file, fileList)
}

// 上传失败
const handleError: UploadProps['onError'] = (err, file, fileList) => {
	ElMessage.error('上传失败')
	emit('error', err, file, fileList)
}

// 删除文件
const handleRemove: UploadProps['onRemove'] = (file, fileList) => {
	emit('update:modelValue', fileList)
}

// 暴露方法，让父组件可以手动提交 / 清空
defineExpose({
	submit: () => uploadRef.value?.submit(),
	clearFiles: () => uploadRef.value?.clearFiles(),
})
</script>

<style scoped lang="less">
.imgWrap {
	display: flex;
	justify-content: center;
	margin-right: 10px;
}
.avatar {
	height: auto;
	width: 100%;
}
/* 拖拽区域高度可定制 */
.el-upload-dragger {
	padding: 40px 0;
}
.avatar-uploader .el-upload {
	border: 1px dashed var(--el-border-color);
	border-radius: 6px;
	cursor: pointer;
	position: relative;
	overflow: hidden;
	transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
	border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
	font-size: 28px;
	color: #8c939d;
	width: 100%;
	height: 100%;
	text-align: center;
	border: 1px dashed #8c939d;
}
.uploadRef {
	display: flex;
}
.el-upload__tip {
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	p {
		font-weight: 400;
		font-size: 14px;
		color: rgba(0, 0, 0, 0.6);
		line-height: 22px;
	}
	> div {
		font-weight: 400;
		font-size: 16px;
		color: #006d7a;
	}
}
</style>
